package edu.cuit.avatar.method;

import java.util.Scanner;

public class PrintCalendar {
    public static void main(String[] args) {
        //子问题1:读取用户输入
        System.out.println("Enter full year.(eg..2018):");
        Scanner input = new Scanner(System.in);
        int year = input.nextInt();
        System.out.println("Enter month as number between 1 and 12:");
        int month = input.nextInt();
        input.close();
        //子问题2: 根据输入打印日历
        printCalendar(year, month);

        Integer.parseInt("100");
    }

    /**
     * 打印日历
     * @param year 年份
     * @param month 月份
     */
    public static void printCalendar(int year, int month){
        //子问题1: 打印日历标题
        printMonthTitle(year, month);
        //子问题2: 打印日历主体
        printMonthBody(year, month);
    }

    /**
     * 打印日历标题(月历的标题由三部分组成：年月，虚线，每周7天的星期名称)
     * @param year 年份
     * @param month 月份
     */
    public static void printMonthTitle(int year, int month){
        //获取代表该月名称
        String monthName = getMonthName(month);
        System.out.println("         " + monthName + "  " + year);
        System.out.println("---------------------------------------------");
        System.out.println(" Sun Mon Tue Wed Thu Fri Sat ");
    }

    /**
     * 根据数字月份获取该月名称
     * @param month 数字月份
     * @return 月份名称
     */
    public static String getMonthName(int month){
        String[] monthNames = {"January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December"};
//        return switch (month){
//            case 1 -> "January";
//            case 2 -> "February";
//            case 3 -> "March";
//            case 4 -> "April";
//            case 5 -> "May";
//            case 6 -> "June";
//            case 7 -> "July";
//            case 8 -> "August";
//            case 9 -> "September";
//            case 10 -> "October";
//            case 11 -> "November";
//            case 12 -> "December";
//            default -> "";
//        };
        return monthNames[month - 1];
    }
    /**
     * 打印日历主体
     * @param year
     * @param month
     */
    public static void printMonthBody(int year, int month){
        //子问题1: 获取该月的第一天为星期几(计算缩进)
        int startDay = getStartDay(year, month);
        //子问题2: 获取该月总天数
        int numberOfDaysInMonth = getNumberOfDaysInMonth(year, month);
        int i = 0;
        for(i = 0; i < startDay; i++)
            System.out.print("    ");
        for(i = 1; i <= numberOfDaysInMonth; i++) {
            System.out.printf("%4d", i);
            if((i + startDay) % 7 == 0) System.out.println();
        }
        System.out.println();
    }

    /**
     * 计算指定年月第一天为星期几
     * 假设知道1800年1月1日是星期三（START_DAY_FOR_JAN_1_1800 = 3),然后计算1800-01-01和日历月份的第一天之间相差的总天数（totalNumberOfDays）。因为每个星期有7天，所以日历月份第一天的星期就是（totalNumberOfDays + START_DAY_FOR_JAN_1_1800 ） % 7
     * @param year 年份
     * @param month 月份
     * @return 该月第一天为星期几
     */
    public static int getStartDay(int year, int month){
        final int START_DAY_FOR_JAN_1_1800 = 3;
        //计算从1800-01-01到指定年月中间相差的总天数
        int totalNumberOfDays = getTotalNumberOfDays(year, month);

        return (totalNumberOfDays + START_DAY_FOR_JAN_1_1800) % 7;
    }

    /**
     * 指定月份总天数
     * @param year 年份
     * @param month 月份
     * @return 该月的总天数
     */
    public static int getNumberOfDaysInMonth(int year, int month){
        return switch(month){
            case 1, 3, 5, 7, 8, 10, 12 -> 31;
            case 4, 6, 9, 11 -> 30;
            case 2 -> isLeapYear(year) ? 29 : 28;
            default -> 0;
        };
    }

    /**
     * 计算从1800-01-01到指定年月中间相差的总天数
     * @param year 年
     * @param month 月
     * @return 总天数
     */
    public static int getTotalNumberOfDays(int year, int month){
        int total = 0;
        for(int i = 1800; i < year; i++)
            total += isLeapYear(i) ? 366 : 365;

        for(int i = 1; i < month; i++)
            total += getNumberOfDaysInMonth(year, i);
        return total;
    }

    /**
     * 计算该年是否为闰年
     * @param year 年份
     * @return 闰年: true
     */
    public static boolean isLeapYear(int year){
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    }
}
